perm filename SPLAY.FAI[SAM,LCS]1 blob sn#437774 filedate 1979-05-02 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00035 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00005 00002		TITLE PLAY
C00008 00003		SUBTTL Data Formats
C00009 00004	PLAY:	0
C00019 00005	----- RPGSA			RPG entry point
C00020 00006	----- DOINIT			Open files and initialize
C00025 00007	----- MAINLP			Main loop
C00027 00008	NSUBR TTYIN
C00031 00009	NSUBR ESCI			Handle <ESC>I,  also ALTCHK
C00035 00010	----- DIE			Flush anything still active and exit
C00036 00011	NSUBR RDMAIL			Read mail and perhaps decide what to do
C00039 00012	NSUBR SAMINI			Initialize the Samson Box.
C00047 00013	NSUBR SAMGO			Start Samson Box
C00048 00014	NSUBR SIXMSG			Process message from SIX
C00051 00015	----- MINT - Print information (Samson Box interrupt)
C00054 00016	----- MCDONE - Command buffer done (send another)
C00057 00017	----- MRDONE - Read data done (send another)
C00058 00018	----- MWDONE - Write data done (send to disk and setup next)
C00059 00019	----- ADCDONE - ADC buffer done (send another)
C00060 00020	NSUBR MSGWAIT,CODE		Wait for specified message type
C00063 00021	NSUBR GETSCM,COUNT		Get SCM buffer (also GETAUX)
C00066 00022	NSUBR SNDSCM,COUNT		Send command buffer to SAM (also SNDAUX)
C00070 00023	NSUBR SETOUT,COUNT		Send data buffer to SAM (also SNDOUT)
C00072 00024	NSUBR SETADC,COUNT		Send data buffer to ADC
C00073 00025	NSUBR ENDSCM			Send special trailer buffer to SAM
C00075 00026	NSUBR RCVMSG			Recieve message from SIX
C00076 00027	NSUBR SNDMSG,CODE,DATA,SIZE	Send message to SIX (device)
C00078 00028	NSUBR SNDMS1,CODE		Send one word message to SIX (device)
C00079 00029	NSUBR PRTMSG			Print message
C00081 00030	NSUBR WAITON,CONDITIONS		Wait for one of several events
C00083 00031	----- INTSER			Interrupt service routine
C00084 00032	NSUBR SNDINT			Send interrupt to calling program
C00085 00033	NSUBR SWNUM			Get number from switch name (from FCOPY)
C00088 00034	Typeout to arbitrary TTY, using NULMES
C00091 00035	Data area
C00100 ENDMK
C⊗;
	TITLE PLAY
	ENTRY PLAY
↓msgbug←←1	;Message debugging (leave on)
↓intbug←←0	;Interrupt debugging
↓ADSSAM←←3	;Audio Switch channel for Samson Box.
ifndef membug,< ↓membug←←0 >	;Kludge to avoid top 32K of memory!!!!
↓tmoenb←←0	;Enable timeout feature (if non-zero)

;;;	PRINTS/A program to drive Samson Box from SAM file
;;;/
ifn intbug,<	prints/⊗ Interrupt debugging code included.
/>
;;;ifn msgbug,<	prints/⊗ Message printing code included.
;;;/>
ifn membug,<	prints/******** Horrible kludge to skip top of memory included *****
/>

.INSERT HEADER.FAI[1,TVR]
.INSERT INTDEF.FAI[1,TVR]
.INSERT RPGDEF.FAI[1,TVR]
.INSERT MESDEF[SIX,MUS]
.INSERT DEVDEF[SIX,MUS]
.INSERT DACDEF[SIX,MUS]
.INSERT SAMDEF[SIX,MUS]
.LIBRARY TVRLIB.REL[SUB,SYS]

	EXTERNAL JOBCNI,JOBAPR

;Parameters
↓MAXBFS←←=10	;Maximum number of buffers which may be used for SAM
↓MSGMSZ←←=64+3	;Maximum message size
↓TAILSZ←←=28	;Size of trailer (to make sure command buffer done
		;means command list is done)

;Definitions
↓RET←1
↓RET2←RET+1
↓T←3
↓T2←T+1
↓A←4
↓B←A+1

↓SCMCHN←←1	;Input (SCM) file
↓AUXCHN←←3	;Read data (SDA) file
↓OUTCHN←←2	;Write data (SDA) file
↓SIXCHN←←4	;SIX channel
↓SAMCHN←←5	;SAM interlock device
↓ADCCHN←←6	;ADC interlock device

↓DEVWAI←←1000	;Wait for device
↓DEVNWA←←400	;Take error return if busy (No wait)

↓SIXDEV←←SYSDEV	;Handy alias

;Bits for CONOA SAM, ('Sam ConoA')
↓SCAHLT←←200000		;Stop clock ('halt')
↓SCAGO ←←400000		;Start clock ('go')
↓SCASTP←←600000		;Cause one tick ('step')
↓SCACLT←←100000		;Reset tick counter ('clear ticks')
↓SCAPRO←←004000		;Permit processing ticks
↓SCAUPD←←010000		;Update ticks only
↓SCAMR ←←000010		;Master reset

;Fields for CONOB SAM,
↓DR20B←←27		;Select one 20 bit samples/word

;Special commands
↓CLRPAS←←430		;Clear pass counter, linger of 0
↓SCMNOP←←0		;NOP command

	SUBTTL Data Formats

;Letters from MAIL UUO
COMMENT ⊗
	Job number of caller			;0
	unused					;1
	unused					;2
	SIXBIT/function/			;3
	TTY number				;4
	Interrupt bit to send on completion	;5
	unused (or arg 1)			;6
	unused (or arg 2)			;7
	SIXBIT/device/				;10
	unused					;11
	SIXBIT/file/				;12
	SIXBIT/ext/				;13
	unused					;14
	SIXBIT/pppn/				;15
⊗;
↓MLJOB←←0	;Job number
↓MLCMD←←3	;Command name
↓MLINT←←5	;Interrupt bits
↓MLIOSP←←10	;I/O specification index
↓MLARG1←←6
↓MLARG2←←7
PLAY:	0
START:	SKIPA
	  JRST RPGSA		;RPG starting address
	RESET
	MOVE P,PDLIOWD		;Set up stack
	PUSHJ P,[		;Do primary initialization
	INIT1:	MOVE 1,JOBFF		;Core down perhaps
		SKIPN JOBDDT↑		;Debugging?
		  CORE 1,		;  No, then we don't need symbols
		    JFCL
		SETZM BEGZER		;Zero non-constant data area
		MOVE 1,[XWD BEGZER,BEGZER+1]
		BLT 1,ENDZER
		SETOM PACKED		;Assume packed read data at first
	;Initialize for type out
		MOVEI 1,TYOSIZ	;Number of bytes in buffer
		MOVEM 1,TYOLFT
		MOVE 1,[POINT 7,TYOBUF]	;Point at beginning of buffer
		MOVEM 1,TYOPTR
		POPJ P,]
	MOVSI 1,'TTY'		;Output to normal TTY
	MOVEM 1,TYOTTY
	MOVEI 1,1		;Assume one play
	MOVEM 1,RPTCNT
	RESCAN RESCNT		;Get at command arguments, count→2
RESLOO:	SOSL RESCNT		;Any characters left in arguement
	  INCHSL 1		;Get it then
	JRST START1		;None left, ask user explicately
	CAIN 1,";"		;Beginning of arguments?
	  JRST START0		;  Yes, start without prompt
	CAIE 1,12		;End of line?
	  JRST RESLOOP		;  No, go back for more
START1:	SKIPLE RESCNT		;Flush any extra crud (might have been
	  INCHSL 1		;hacking DDT
	    SKIPA
	  JRST START1		;More crud to flush
;;	OUTSTR[ASCIZ/
;;*/]
START0:	;First, read output file, but might also be input file
	;Read input file
	SETZM OUTFILE		;Mark as unused
	SETZM AUXFILE		;Mark as unused
	JRST DOINIT
;GO PLAY TEST.SAM

	CALL RDIOSP↑,<[OUTBLK+1]>,<[PUSHJ P,CMDGET]>,<[SIXBIT/SAM/]>
	  JRST START1		;Blank line, give out a prompt
   	CAIN 1,"/"		;How about switch processing
   	  PUSHJ P,DOSWITCH	;  Sure, try it
	CAIN 1,15		;CR?
	PUSHJ P,CMDGET		;  Yes, read ever present LF
	CAIE 1,"←"
	JRST [	;Yes, use same file with different extensions
		PUSH P,INBLK+2		;Save buffer header
		MOVE 2,[XWD OUTBLK+1,INBLK+1]	;and copy file spec.
		BLT 2,INFILE+3
		POP P,INBLK+2
		HLRZ 2,OUTFILE+1	;If default output is given
		CAIN 2,'TEST'		;then use default input
		  MOVEI 2,'SAM'		;extension
		HRLM 2,INFILE+1
		SETZM OUTFILE		;Mark as unused
		MOVE 2,OUTSIZ		;Set buffer size
		MOVEM 2,SCMSIZ
		JRST AUXCHK ]		;Don't ask for input
GETIN:	CALL RDIOSP↑,<[INBLK+1]>,<[PUSHJ P,CMDGET]>,<[SIXBIT/SAM/]>
	  JRST START3		;Blank, must be confused
AUXCHK:	CAIN 1,"/"		;How about some switch processing?
	  PUSHJ P,DOSWITH	;  Sure, at least think about it
	CAIN 1,","
	  JRST[	CALL RDIOSP,<[AUXBLK+1]>,<[PUSHJ P,CMDGET]>,<[SIXBIT/SDA/]>
		  JRST START3
		JRST AUXCHK]
	CAIN 1,"?"
	  JRST HELPME
	CAIN 1,15		;Flush ever present LF after CR
	PUSHJ P,CMDGET
	CAIE 1,12		;Better be end of line
START3:	JRST [	CAIN 1,"?"	;Need help?
		  JRST HELPME	;  Yes
		OUTSTR[ASCIZ/
I don't understand, try again.  Type ? for help./]
		JRST START1 ]
	JRST DOINIT

HELPME:	OUTSTR[
  HELPMSG:	ASCIZ $
This program sends commands from a disk file to the Samson Box.  It
expects to see a file name as input.  You may also include the following
switches which affect the way the program works:

/REPEAT=3	Repeat 3 times
/PAUSE=2	Pause 2 seconds between repeats (Doesn't work)
/WAIT		If someone is already using SAM, wait for him/her to finish.
/NOMAP		Don't switch the console speaker to SAM channel 1
/TAPE		Wait until 'GO' is typed before playing
/HOG		Don't let go of SAM between plays
/LOCK		Lock job in core
/MEMDEB		Prints memory buffer addresses
/EXIT		Exit after playing specified repetitions.
/DEBUG		Causes debugging information to be printed
/BUFSIZ		Set buffer size in 128 wd records
/BUFCNT		Set number of buffers to use
/ADC		Take input from ADC instead of disk
/ADSIZE		Specify size of ADC's buffer
/OVERWR		Over-writes output file.  This makes it go faster.
/HELP		Print this cruft

For example:

	.R SAMPHA
	*SOLFEG.SAM[SAM,MUS]/EXIT

Plays SOLFEG.SAM[SAM,MUS] once and then exits to the monitor.

	.R SAMPHA;TEST20/REPEAT=5/WAIT

Waits for SAM to be available and plays TEST20.SCM (from your current
disk area) five times.

$]
	JRST START1		;Now, try again

;Switch processing
DOSWIT:	CALL SWNUM		;Get switch by number
	SETZ RET,		;Default argument of 0
	CAIE 0,"="		;Is there a numeric argument?
	  JRST NOARGS
	CALL RDINT↑,<[=10]>,<[PUSHJ P,CMDGET]>
	SKIPA
NOARGS:   TLO RET2,400000
	XCT SWXCT(RET2)
	MOVE RET,0
	CAIE RET,"/"		;Another switch?
	  POPJ P,		;  No, done
	JRST DOSWIT		;Repeat until they've all been eaten

;Switches known herein
SWTAB:	SIXBIT/REPEAT/
	SIXBIT/PAUSE/
	SIXBIT/WAIT/
	SIXBIT/NOMAP/
	SIXBIT/EXIT/
	SIXBIT/HELP/
	SIXBIT/DEBUG/
	SIXBIT/BUFSIZ/
	SIXBIT/BUFCNT/
	SIXBIT/TAPE/
	SIXBIT/HOG/
	SIXBIT/LOCK/
	SIXBIT/MEMDEB/
	SIXBIT/PACKED/
	SIXBIT/UNPACK/
	SIXBIT/ADC/
	SIXBIT/OVERWR/
	SIXBIT/ADSIZE/
↓SWCNT←←.-SWTAB

SWXCT:	PUSHJ P,[		;REPEAT
		SKIPL RET2		;Argument given?
		  MOVEM RET,RPTCNT	;  Yes, store it
		POPJ P,]
	PUSHJ P,[		;PAUSE (cop-out)
		OUTSTR[ASCIZ/Pause feature not implemented
		MOVEM RET,WAITCNT
/]↔		POPJ P,]
	SETCMM WAITFL		;WAIT - Always wait for SAM
	SETCMM NOMAP		;NOMAP - Don't map the audio switch!
	SETCMM ONCE		;ONCE - Play once and leave
	OUTSTR HELPMSG		;HELP
	SETCMM DEBUG		;DEBUG - Print debugging information
	PUSHJ P,[		;BUFSIZ
		IMULI RET,=128
		SKIPG RET2		;Argument given?
		  POPJ P,
		SKIPE AUXFIL		;For Auxillary?
		  JRST[	MOVEM RET,AUXSIZ	;  Yes, store it
			POPJ P,]
		SKIPE INFILE		;For Input?
		  JRST[	MOVEM RET,SCMSIZ	;  Yes, store it
			POPJ P,]
		SKIPE OUTFILE		;For Output?
		  JRST[	MOVEM RET,OUTSIZ	;  Yes, store it
			POPJ P,]
		POPJ P,]
	PUSHJ P,[		;BUFCNT
		SKIPL RET2		;Argument given?
		  MOVEM RET,NBUFS	;  Yes, store it
		POPJ P,]
	SETCMM TAPEFL		;TAPE - wait for GO before playing
	SETCMM GRABBY		;HOG - don't let go of SAM
	SETCMM LOCKFL		;LOCK - lock program in core
	SETCMM MEMDEB		;MEMDEB - print memory buffer addresses
	SETOM PACKED		;PACKED - packed input file (16 bit)
	SETZM PACKED		;UNPACKED - unpacked input file  (20 bit)
	SETOM ADCFLG		;ADC - Enable ADC operation
	SETOM OVERWR		;OVERWR - Overwrite, don't create new file
	PUSHJ P,[		;ADSIZE - Set size of ADC buffer
		IMULI RET,=128
		SKIPLE RET2		;Argument given?
		  MOVEM RET,AUXSIZ	;  Yes, store it
		POPJ P,]
;----- RPGSA			;RPG entry point

RPGSA:	MOVE P,PDLIOWD		;Set up stack
	PUSHJ P,INIT1		;Do primary initialization
	MOVEM RPGDEV,INDEV
	MOVEM RPGFIL,INFILE
	MOVEM RPGEXT,INFILE+1
	MOVEM RPGPPN,INFILE+3
	CAIG RPGLIN,200		;Check line number
	  MOVEM RPGLIN,TYOTTY	;If OK, set TTY number
;	JRST DOINIT

;fall thru to next page
;----- DOINIT			;Open files and initialize
;fall thru from previous page
	BEGIN DOINIT

↑DOINIT: INIT SIXCHN,17
	    SIXBIT/SIX/
	    0
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Can't INIT device SIX, you can't run the Samson Box./]]>,TYOOP
		JRST DIE]
	OPEN SCMCHN,INBLK		;Open input side first (not really the
				;right thing if input=output file, due
				;to timing loss if two people try to
				;update the same file
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Can't open device: /]]>,TYOOP
		CALL WRSIX↑,INBLK+1,TYOOP
		JRST DIE]
	MOVE 1,INFILE+3		;Save PPN
	LOOKUP SCMCHN,INFILE
	  JRST[	MOVEM 1,INFILE+3	;Restore PPN
		CALL WRASCZ↑,<[[ASCIZ/Can't find file: /]]>,TYOOP
		CALL WRIOSP↑,<[INBLK+1]>,TYOOP
		MOVE 1,INFILE		;Check for HELP
		CAME 1,[SIXBIT/HELP/]
		  JRST DIE
		CALL DOCRLF
		CALL WRASCZ↑,<[HELPMSG]>,TYOOP
		JRST DIE]
	EXCH 1,INFILE+3		;Restore PPN, get count
	MOVS 1,1		;Unfungle count
	MOVNM 1,INWC		;Set word count
	SKIPN AUXFIL		;Open aux. input?
	  JRST SKPAUX
	OPEN AUXCHN,AUXBLK	;Open input side first (not really the
				;right thing if input=output file, due
				;to timing loss if two people try to
				;update the same file
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Can't open device: /]]>,TYOOP
		CALL WRSIX↑,INBLK+1,TYOOP
		JRST DIE]
	MOVE 1,AUXFILE+3	;Save PPN
	LOOKUP AUXCHN,AUXFILE
	  JRST[	MOVEM 1,AUXFILE+3	;Restore PPN
		CALL WRASCZ↑,<[[ASCIZ/Can't find file: /]]>,TYOOP
		CALL WRIOSP↑,<[AUXBLK+1]>,TYOOP
		JRST DIE]
	EXCH 1,AUXFILE+3	;Restore PPN, get count
	MOVS 1,1		;Unfungle count
	MOVNM 1,AUXWC		;Set word count
SKPAUX:	SKIPN OUTFIL		;Open output?
	  JRST SKPOUT
	OPEN OUTCHN,OUTBLK
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Can't open device: /]]>,TYOOP
		CALL WRSIX↑,INBLK+1,TYOOP
		JRST DIE]
	SKIPN OVERWR		;Overwrite mode?
	  JRST NOTOVR		;  No, create new file
	MOVE 1,OUTFIL+3		;Save PPN
	LOOKUP OUTCHN,OUTFILE
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Can't find file to overwrite: /]]>
		CALL WRFILN↑,<[OUTBLK+1]>,TYOOP
		JRST DIE]
	MOVEM 1,OUTFIL+3	;Replace PPN
NOTOVR:	ENTER OUTCHN,OUTFILE
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Can't (over)write file: /]]>,TYOOP
		CALL WRFILN↑,<[OUTBLK+1]>,TYOOP
		JRST DIE]
SKPOUT:	MOVE 1,AUXFIL		;Check for read data active
	OR 1,ADCFLG
	MOVEM 1,RDAFLG
	PJOB 1,			;Get this job's number
	MOVEM 1,THISJOB
	MOVEI RET,INTSER	;Set interrupt service routine
	MOVEM RET,JOBAPR
	INTMSK [0]		;Don't allow any interrupts
	MOVE RET,[INTTTY!INTMAIL!INTTTI!INTSIX]
	INTENB RET,		;Enable interrupts
	
	movsi ret,'TTY'		;Check for TTY
	came ret,tyotty
	  jrst [skpme		;  No, wait for mail
		  jrst mainlp
		call rdmail
		jrst mainlp]
	call saminit
	skipe tapefl		;Tape mode?
	  jrst mainlp		;  Yes, wait
	skipe samrdy		;Is it ready
	  call samgo		;  Yes, start it going

;	JRST MAINLP

	BEND DOINIT
;fall thru to next page
;----- MAINLP			;Main loop

;fall thru from previous page
MAINLP:
	CLKINT [=60*=60*1]	;Wait 1 minute(s) before giving up
ifn intbug,<	outchr ["⊗"]	>
	CALL WAITON,<[INTTTY!INTMAIL!INTCLK!INTTTI!INTSIX]]>
	MOVE A,PENDING		;OR in any pending interrupts
	TLNE A,(INTTTY)		;TTY input interrupt
	  JRST[	CALL TTYIN	;  Yes, dealt with it
		MOVSI A,(INTTTY)
		ANDCAB A,PENDING
		JRST .+1]
	TLNE A,(INTTTI)
	  CALL ESCI
	TLNE A,(INTMAIL)	;Mail received?
	  JRST[	CALL RDMAIL	;  Yes, read it
		SETZM PENDING
		JRST MAINLP]	;  Go back for more
	TRNE A,INTSIX		;SIX message?
	  JRST[	CALL RCVMSG	;  Yes, handle generally
		CALL SIXMSG
		MOVEI A,INTSIX
		ANDCAB A,PENDING	;  SIX message is no longer pending
		JRST .+1]
	TLNE A,(INTCLK)
	  JRST[
		MOVSI A,(INTCLK)
		ANDCAB A,PENDING	;  Timeout was handled
IFE TMOENB,<
		SKIPE SAMRDY	;Is SAM ready to run or running?
>;IFE TMOENB
IFN TMOENB,<
		SKIPE TAPEFL	;Don't timeout in tape mode!
>;IFN TMOENB
		  JRST .+1	;  Yes, ignore time-out for now.
		CALL WRASCZ↑,<[[ASCIZ/Timeout - Aborting/]]>,TYOOP
		JRST DIE]
	JUMPE A,MAINLP		;All interrupts serviced
	CALL WRASCZ↑,<[[ASCIZ/Unexpectd return from WAITON, ignoring./]]>,TYOOP
	CALL DOCRLF
	SETZM PENDING
	JRST MAINLP
NSUBR TTYIN

	SNEAKS RET,		;Get first character, if any
	  POPJ P,		;  False alarm
	CAIN RET," "		;Eat any stray spaces

  	  JRST[	INCHRS RET	;  If we can
  		  POPJ P,	;    Cheap insurance
  		JRST TTYIN]

	CAIE RET,"g"
	CAIN RET,"G"		;G is for Go from TAPE switch
	  JRST[	CALL EATLIN	;  Eat the rest of the line
		SKIPN SAMRDY	;  Is it ready?
		  JRST[	OUTSTR[ASCIZ/Not ready, need a repeat count first.
/]↔			JRST TTYIN]
		CALL SAMGO	;  Start it running
		JRST TTYIN]	;  Look for more crud
	CAIN RET,";"		;For talking
	  JRST[	CALL EATLIN
		JRST TTYIN]	;  Look for more crud
	CAIE RET,"y"
	CAIN RET,"Y"		;Y means wait for box (if not present)
	  JRST[	CALL EATLIN
		SETOM WAITFL	;  Now, always wait
		JRST RETRY]	;  And try again
	CAIE RET,"n"
	CAIN RET,"N"		;N means give up
	  JRST[	CALL EATLIN
		JRST DIE]
	CAIE RET,12		;<lf>
	CAIN RET,15		;<cr>
	  JRST[	CALL EATLIN	;  Flush and leave
		JRST DIE]
	CAIN RET,175		;<alt>
	  CALL ALTCHK		;   This will print a nice message
	CAIN RET,"/"		;Is it a switch
	  JRST[	INCHWL RET	;  Yes, curious, but we can do it
		CALL DOSWITCH
		JRST ENDCHK]
;If none of the above, assume it's a number (ha,ha)
	CALL RDINT↑,<[=10]>,<[PUSHJ P,CMDGET]>
	MOVEM RET,RPTCNT	;Set repeat count
	CAIN 0,"/"		;Switch?
	  CALL DOSWITH		;  Why not try.
	CAIE 0,","		;Wait time given?
	  JRST ENDCHK		;  No, check for end of line
	CALL RDINT↑,<[=10]>,<[PUSHJ P,CMDGET]>
	MOVEM RET,WAITIM	;Set pause time
ENDCHK: CAIN 0,15		;Is it a <cr>
	  INCHWL 0		;  Yes, eat companion <lf>
	CAIE 0,12		;Is it a <lf>
	  JRST[	OUTSTR[ASCIZ/???
Number of times to play (or <ALT> to quit): /]
		POPJ P,]
RETRY:	SKIPG RPTCNT		;Repeat count positive?
	  POPJ P,		;  No, don't bother further
	CALL SAMINIT		;Get it ready to go again
	SKIPN TAPEFL		;Taping?
	  CALL SAMGO		;  No, start it now!
	POPJ P,			;Go for more stuff

EATLIN:	INCHRS RET		;Consume to <cr> or <lf>
	  POPJ P,		;  Hmmm, end of the line came a bit early
	CAIN RET,12
	  POPJ P,
	CAIE RET,175		;<alt>?
	  JRST EATLIN		;  No, eat some more crud from line
ALTBYE:	CALL WRASCZ↑,<[[ASCIZ/Flushed/]]>,TYOOP
	JRST DIE

SUBREND TTYIN
NSUBR ESCI			;Handle <ESC>I,  also ALTCHK

	CALL WRASCZ↑,<[[ASCIZ/<esc>I - Aborting.../]]>,TYOOP
	SETZM PENDING
	CALL DOCRLF
	CALL SNDMS1,<[MCONIA,,SAMDEV]>
	CALL SNDMS1,<[MCONIB,,SAMDEV]>
	CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAHLT]]>,<[1]>	;Stop its clock
	CALL MSGWAIT,<[MCONIA,,SAMDEV]>
	CALL SIXMSG
	CALL MSGWAIT,<[MCONIB,,SAMDEV]>
	CALL SIXMSG
	MOVSI RET,'TTY'		;Is this run from console mode?
	CAME RET,TYOTTY
	  JRST DIE		;  No, exit quickly
	CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAHLT]]>,<[1]>	;Stop its clock
	SKIPE LOCKFL		;Was it maybe locked?
	  UNLOCK		;  Yes, unlock it!
CMDLP:	CALL WRASCZ↑,<[[ASCIZ/Dump delay_memory from (<ALT> to exit): /]]>,TYOOP
	CALL TYOFLUSH
	CALL RDINT↑,<[8]>,<[PUSHJ P,CMDGET]>
	CAIN 0,175
	  JRST DIE
DMPSIZ←←8*8
	MOVE B,RET		;Save address for printing purposes
	CAIN 0,15		;CR?
	  PUSHJ P,CMDGET	;  Yes, get corresponding LF
	HRLI B,-DMPSIZ
	MOVEM B,MSGDAT
	CALL SNDMSG,<[MDMRW,,SAMDEV]>,<[0]>,<[1+DMPSIZ]>
				;Write randomness and get data from memory
	CALL MSGWAIT,<[MDMRW,,SAMDEV]>
				;Wait for read data
	CALL SNDMSG,<[MDMWR,,SAMDEV]>,<[0]>,<[1+DMPSIZ]>
				;Write original data back
	MOVSI A,-DMPSIZ		;Setup to dump to terminal
DMPLP:	TRNE A,7		;Time to start new line?
	  JRST SKPADR		;  No, do more will fit on this line
	TRNE A,-1		;First line?
	  CALL DOCRLF		;  No, CRLF between lines
	HRRZ RET,A
	ADDI RET,(B)
	CALL WROCT↑,RET,<[6]>,TYOOP	;Print address
SKPADR:	MOVEI RET,11		;TAB to separate
	XCT TYOOP
	CALL WROCT↑,<MSGDAT+1(A)>,<[7]>,TYOOP	;Print a location
	AOBJN A,DMPLP		;Repeat for each word in memory
	CALL DOCRLF		;Final CRLF
	JRST CMDLP

SUBREND ESCI

NSUBR ALTCHK			;Check for <alt>

	MOVSI RET,INTTTY	;We've look at this one
	ANDCAM RET,PENDING
	SNEAKS RET,		;Is there anything there?
	  POP0J			;  No, forget it!
	CAIE RET,175		;Is it an <alt>
	  POP0J			;  No, ignore for now.
	CALL WRASCZ↑,<[[ASCIZ/Flushed/]]>,TYOOP
	JRST DIE

SUBREND ALTCHK
;----- DIE			;Flush anything still active and exit
DIE:	CALL DOCRLF		;Flush out any messages
QDIE:	RESET			;Flush any I/O
	CLRBFI
	HRRZ 1,120		;GET STARTING ADDRESS FOR RETURN HOME
	JRST (1)		;GO THERE.
;;	EXIT 1,			;Leave quickly
;NSUBR RDMAIL			;Read mail and perhaps decide what to do

RDMAIL:	SRCV MAILBOX			;Is there mail?
	  POPJ P,			;  False alarm, just return
	MOVE RET,MAILBOX+MLCMD		;Get command
	CAMN RET,[SIXBIT/ABORT/]	;Abort command?
	  JRST QDIE			;  Yes, flush everything and leave
	CAMN RET,[SIXBIT/REINIT/]	;Restart?
	  JRST[	MOVE RPGDEV,MAILBOX+MLIOSP	;Setup RPG ACs
		MOVE RPGFIL,MAILBOX+MLIOSP+2
		MOVE RPGEXT,MAILBOX+MLIOSP+3
		MOVE RPGPPN,MAILBOX+MLIOSP+5
		MOVE RPGLIN,TYOTTY
		RESET
		JRST RPGSA ]
	CAMN RET,[SIXBIT/PLAY/]		;Start or continue playing
	  JRST[	CALL PLAYARGS		;  Setup arguments for PLAY
		SKIPN SAMRDY		;  Already setup?
		  CALL WSAMINIT		;    No, initialize it
		SKIPN SAMRUN		;  Already running?
		  CALL SAMGO		;    No, Start it running
		POPJ P,]		;  Done
	CAMN RET,[SIXBIT/WAIT/]
	  JRST[	CALL PLAYARGS		;  Setup arguments for PLAY
		SKIPN SAMRDY		;  Already setup?
		  CALL WSAMINIT		;    No, initialize it
		SKIPN SAMRUN		;  Already running?
		  CALL SAMGO		;    No, Start it running
		POPJ P,]		;  Done
	CAMN RET,[SIXBIT/SAMINI/]
	  JRST[	CALL PLAYARGS		;  Setup arguments for PLAY
		SKIPN SAMRDY		;  Already running?
		  CALL SAMINIT		;    No, Start it running
		POPJ P,]		;  Done
	CAMN RET,[SIXBIT/GO/]
	  JRST[	CALL PLAYARGS		;  Setup arguments for PLAY
		SKIPN SAMRUN		;  Already running?
		  CALL SAMGO		;    No, Start it running
		POPJ P,]		;  Done
	CALL WRASCZ↑,<[[ASCIZ/Unknown command: /]]>,TYOOP
	CALL WRSIX↑,MAILBOX+MLCMD,TYOOP
	CALL DOCRLF
	POPJ P,

;Setup arguments for PLAY or WAIT
PLAYAR:	MOVE RET,MAILBOX+MLARG2	;  Set wait time, if any
	MOVEM RET,WAITIM
	MOVE RET,MAILBOX+MLARG1	;  Add number of times to play
	EXCH RET,RPTCNT		;  Preserve whether running before
	ADDM RET,RPTCNT
	POPJ P,
NSUBR SAMINI			;Initialize the Samson Box.

	SKIPN WAITFL		;Always wait?
	  SKIPA 1,[DEVNWA]	;  No, Don't wait
↑WSAMIN: MOVEI 1,DEVWAI		;Wait for device
	INIT SAMCHN,(1)		;Get the Box
	    SIXBIT/SAM/
	    0
	  JRST[	CAIN 1,DEVWAI+17	;Were we waiting?
		  JRST NOSAM
		CALL WRASCZ↑,<[[ASCIZ/SAM is busy, will you wait? /]]>,TYOOP
		CALL DOCRLF
		POP0J]
	SKIPN ADCFLG		;Get ADC?
	  JRST SKPADC
	INIT ADCCHN,
	    SIXBIT/ADC/
	    0
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Can't INIT ADC (it is unavailable). /]]>,TYOOP
		JRST DIE ]
SKPADC:
;;;	PRINTS/Not zeroing delay memory yet!
;;;/
	CALL SNDMS1,<[MDBLAST,,SAMDEV]>	;Flush any old crud which may be running
	CALL MSGWAIT,<[MDBLAST,,SAMDEV]>	;Wait for it
	SKIPE LOCKFL		;Lock in core?
	  LOCK			;  Yes!
ifn membug,<
;Eat whole top of memory!!!!!
	call sndmsg,<[mgbuf,,sixdev]>,<[[=32*=1024]]>,<[1]>
	call msgwait,<[mgbuf,,sixdev]>
	pushp msgdat
	skipl msgdat
	  jrst[	skipe scmwcma
		  jrst .+1
		call wrascz↑,<[[asciz/This will probably lose!
/]]>,tyoop
		jrst .+1]
	hrrzs (p)
>;ifn membug
	MOVEI B,[SETZ SCMWCMA(A)	;Commands
		 INFILE
		 SCMSIZ
		 SETZ AUXWCMA(A)	;Read Data
		 RDAFLG
		 AUXSIZ
		 SETZ OUTWCMA(A)	;Write Data
		 OUTFILE
		 OUTSIZ
		 0]		;(end of list)
TYPLP:	SKIPN @1(B)		;Is there a file there?
	  JRST NOFILE		;  No, don't get buffers then.
	MOVE A,NBUFS		;Get number of buffers to use
	SUBI A,1		;Table starts at 0, not 1
GBUFLP:	SKIPE @(B)		;Is there something already there?
	  JRST GBUFEC		;  Yes, buffer OK
	CALL SNDMSG,<[MGBUF,,SIXDEV]>,<2(B)>,<[1]>	;Get a buffer
	CALL MSGWAIT,<[MGBUF,,SIXDEV]>	;Wait for it
	SKIPN MEMDEB		;Print memory usage?
	  JRST NOMMDB		;  No
	CALL WRASCZ↑,<[[ASCIZ/Buffer at /]]>,TYOOP
	CALL WROCT↑,MSGDAT,<[6]>,TYOOP
	CALL WRASCZ↑,<[[ASCIZ/ of /]]>,TYOOP
	HLRE RET,MSGDAT		;Get negative of count
	MOVN RET,RET
	CALL WRINT↑,RET,<[8]>,TYOOP
	CALL DOCRLF
NOMMDB:	MOVE RET,MSGDAT		;Get WCMA
	JUMPGE RET,[CALL WRASCZ↑,<[[ASCIZ/Not enough buffer space on SIX. - Aborting/]]>,TYOOP
		JRST DIE]
	MOVEM RET,@(B)		;Save WCMA for this buffer
GBUFEC:	SOJGE A,GBUFLP		;Repeat for each buffer
NOFILE:	ADDI B,3		;Advance to next in list of things wanting buffers
	SKIPE (B)		;Is this the end of the list
	  JRST TYPLP		;  No, more buffers wanted, perhaps
ifn membug,<
	skipl (p)
	  jrst foo2
;Give back the top of core!!!
	movei ret,(p)
	call sndmsg,<[mgivb,,sixdev]>,ret,<[1]>
	call msgwait,<[mgivb,,sixdev]>
foo2:	pop p,(p)
>;ifn membug
	SETZM SCMNXT
	SETZM AUXNXT
	SETZM OUTNXT
;Alternate entry point to repeatedly playing
↑SAMSET: 
	SETZM SCMACT
	SETZM SCMLST
	SETZM AUXACT
	SETZM OUTACT
	CALL SNDMS1,<[MSTIFL,,SAMDEV]>	;Clear all processing elements
	CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAGO!SCACLT!SCAUPD]]>,<[1]>
				;Start running with update ticks, only
	SKIPE PACKED		;Which read data format
	  JRST ISPACK		;  Two 16 bit samples/word
	CALL SNDMSG,<[MCONOB,,SAMDEV]>,<[[DR20B]]>,<[1]>
				;Select one 20 bit sample/word
ISPACK:	CALL SNDMSG,<[MDTA,,SAMDEV]>,<[[CLRPAS]]>,<[1]>
↑SAMST2: USETI SCMCHN,1		;Set to beginning of file
	SETZM INADR
LOADLP:	CALL GETSCM,SCMSIZ	;Get a buffer, if any
	  JRST[	CALL ENDSCM	;  EOF, put out funny trailer
		JRST AUXSET]
	CALL SNDSCM,RET
	MOVE RET,SCMACT		;Check number of active buffers
	CAMGE RET,NBUFS		;Are they all full?
	  JRST LOADLP		;  No, more to go
AUXSET:	SKIPE ADCFLG		;ADC mode?
	  JRST AUXLP		;  Yes, skip USETI and set 'er up
;;;prints/*** For some reason, REPEAT doesn't repeat Read Data.  Problem should be
;;;here but doesn't seem to be!
;;;/
	SKIPN AUXFIL		;Is there something to send?
	  JRST OUTSET		;  No, we're done
	USETI AUXCHN,1		;Set to beginning of file
AUXLP:	CALL GETAUX,AUXSIZ	;Get a buffer, if any
	  JRST OUTSET		;  OK, done
	CALL SNDAUX,RET
	MOVE RET,AUXACT		;Check number of active buffers
	CAMGE RET,NBUFS		;Are they all full?
	  JRST AUXLP		;  No, more to go
OUTSET:	SKIPN OUTFIL		;Is there something to send?
	  JRST ADCSET		;  No, we're done
	USETO OUTCHN,1		;Set to beginning of file
OUTLP:	CALL SETOUT,OUTSIZ	;Prepare next buffer
	MOVE RET,OUTACT		;Check number of active buffers
	CAMGE RET,NBUFS		;Are they all full?
	  JRST OUTLP		;  No, more to go
ADCSET:	SKIPN ADCFLG		;Reading from ADC?
	  JRST SETRDY		;  No, done
	CALL SNDMSG,<[MSPAR,,ADCDEV]>,<[[400000+3*1000+1*100+42]]>,<[1]>
;Datum:		(thresh + mpx),,(speed*1000 + pack*100 + SAMBIT*40 + Nchannels)
				;*** Temporary packing mode
	CALL MSGWAIT,<[MSPAR,,ADCDEV]>	;Wait for it
	CALL SNDMS1,<[MFSTB,,ADCDEV]>
				;Clear data missed flag
ADCLP:	CALL SETADC,AUXSIZ	;Setup buffer for ADC
	MOVE RET,ADCACT		;Are they all full?
	CAMGE RET,NBUFS		;Are they all full?
	  JRST ADCLP		;  No, more to go
SETRDY:	SETOM SAMRDY		;SAM is ready to GO
	SKIPN TAPEFL		;Is message needed?
	  POP0J			;  No, just leave
	CALL WRASCZ↑,<[[ASCIZ/Type GO when ready: /]]>,TYOOP
	CALL TYOFLUSH
	POP0J

NOSAM:	CALL WRASCZ↑,<[[ASCIZ/Can't INIT SAM (it is unavailable). /]]>,TYOOP
	JRST DIE

SUBREND SAMINI
NSUBR SAMGO			;Start Samson Box

	skipn samrdy		;Is it ready?
;;;prints/SAMGO+1: Can get here if SAM is taken after asking for number of times to play.
;;;/]
	  halt .		;  No? BUG!!!!!
	MOVSI RET,663000+ADSSAM		;Temporarily select SAM and delay beeps
	SKIPN NOMAP			;Don't map?
	  ADSMAP RET,			;  No, really do selection
	CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAHLT!SCACLT!SCAPRO]]>,<[1]>
		;Stop clock, reset tick counter and allow processing ticks
	CALL SNDMSG,<[MCONOA,,SAMDEV]>,<[[SCAGO]]>,<[1]>
		;Start it running!
	SETOM SAMRUN
	POP0J

SUBREND SAMGO
NSUBR SIXMSG			;Process message from SIX

ifn intbug,<	outchr ["6"]	>

	MOVE RET,MSGBUF		;Get message
	AND RET,[XWD 007777,000777]	;Get only what we're interested in
	MOVSI RET2,-NKNOWN	;Search list of types we know about
SEARCH:	CAME RET,MSGTYP(RET2)	;Is this one of ours?
	  AOBJN RET2,SEARCH	;  No, try next one
	JUMPGE RET2,UNKNOWN	;Give up if we didn't find one
	XCT MSGSUB(RET2)	;Do something about the message
DONE:	POP0J			;Now, we're done

;Complain about lack of knowledge
UNKNOWN: CALL WRASCZ↑,<[[ASCIZ/Unexpected message from SIX: /]]>,TYOOP
ifn msgbug,<
	CALL DOCRLF
	CALL PRTMSG
>;ifn msgbug
ife msgbug,<
	CALL WROCT↑,MSGBUF,<[=12]>,TYOOP
	MOVEI RET,","
	XCT TYOOP
	CALL WROCT↑,MSGBUF+1,<[=12]>,TYOOP
	CALL DOCRLF
	MOVEI RET,","
	XCT TYOOP
	CALL WROCT↑,MSGBUF+2,<[=12]>,TYOOP
	CALL DOCRLF
>;ife msgbug
	JRST DONE

;Message type known here
MSGTYP:	XWD MINT,SAMDEV		;Interrupt from SAM
	XWD MIOV,SAMDEV		;Too many interrupts from SAM
	XWD MCDONE,SAMDEV	;Command buffer done
	XWD MRDONE,SAMDEV	;Read data buffer done
	XWD MWDONE,SAMDEV	;Write data buffer done
	XWD MCONIA,SAMDEV	;Reply to CONI-A
	XWD MCONIB,SAMDEV	;Reply to CONI-B
	XWD MBDONE,ADCDEV	;ADC buffer done
	XWD MSTBUF,ADCDEV	;Ignore response

;Routines to handle SIX messages
MSGSUB:	CALL PRMINT		;Interrupt from SAM
	CALL PRMIOV		;Too many interrupts from SAM
	CALL SCMDONE		;Command buffer done
	CALL AUXDONE		;Read data buffer done
	CALL OUTDONE		;Write data buffer done
	CALL PCONIA		;Reply to CONI-A
	CALL PCONIB		;Reply to CONI-B
	CALL ADCDONE		;ADC buffer done
	JFCL

NKNOWN←←.-MSGTYP

;Too many losing interrupts
PRMIOV:	CALL WRASCZ↑,<[[ASCIZ/Too many SAM interrupts, SIX gives up remembering.
Aborting... /]]>,TYOOP
	JRST DIE		;Probably safest thing
;----- MINT - Print information (Samson Box interrupt)
PRMINT:	SKIPGE MSGDAT		;Get code from message
	  JRST[	SKIPA RET,[[ASCIZ/Interrupt on SAM channel A: /]]
PCONIA:		  MOVEI RET,[ASCIZ/CONI A status: /]
		MOVEI T,TCONIA	;It's a CONI-A
		JRST MINTL1]
	SKIPA RET,[ASCIZ/Interrupt on SAM channel B: /]
PCONIB:	  MOVEI RET,[ASCIZ/CONI B status: /]
	MOVEI T,TCONIB
MINTL1:	CALL WRASCZ↑,RET,TYOOP
	CALL WROCT↑,MSGDAT,<[=6]>,TYOOP
	CALL DOCRLF		;Send it out and go to next line
	MOVE T2,MSGDAT		;Get CONI
	MOVE RET2,-1(T)		;Get first bit to examine
MINTLP:	TDNE T2,RET2		;Was this bit on?
	SKIPG RET,(T)		;and is it to be printed?
	  JRST MINTEC		;  No, do End Check
	CALL WRASCZ↑,RET,TYOOP	;Print message
	CALL DOCRLF		;Send it out and go to next line
MINTEC:	ROT RET2,-1		;Move to next lower bit
	SKIPL (T)		;Done yet?
	  AOJA T,MINTLP		;  No, repeat until out of messages
	POP0J			;End of MINT printout

	200000			;First bit of interest
TCONIA:	[ASCIZ/Command buffer exhausted/]
	[ASCIZ/Write data buffer exhausted/]
	[ASCIZ/Read data buffer exhausted/]
	[ASCIZ/Delay memory parity error/]
	[ASCIZ/SIX memory parity error/]
	[ASCIZ/Non-existant (SIX) memory/]
	[ASCIZ/SAM Running/]
	[ASCIZ/Not being held/]
	[ASCIZ/Command underrun/]
	[ASCIZ/Write data underrun/]
	[ASCIZ/Read data underrun/]
	-1

	100000			;First bit of interest
TCONIB:	[ASCIZ/Command overrun/]		;100000
	[ASCIZ/Mod. Mixer Overflow/]		;040000
	[ASCIZ/Mod. Multiplier Overflow/]	;020000
	[ASCIZ/Mod. Sum Memory Overflow/]	;010000
	[ASCIZ/Gen. Sum Memory Overflow/]	;004000
	0					;002000
	[ASCIZ/'Lost Cause'/]			;001000
	-1

;----- MCDONE - Command buffer done (send another)

SCMDONE:
;;;	PRINTS/Command buffer done routine could use some work.
;;;/
ifn intbug,<	outchr ["!"]	>
	SKIPN SAMRUN		;Running?
	  JRST[	CALL WRASCZ↑,<[[
ASCIZ/Bug: Cmd Buffer done seen with SAMRUN false!/]]>,TYOOP
		CALL DOCRLF
		POP0J ]
	SOS SCMACT		;Decrement number of active command buffers
	SKIPE SCMLST		;Last buffer sent yet?
	  JRST[	SKIPE SCMACT	;  Yes, check for end of whole thing
		  POP0J		;    still some buffers left
;;;		SKIPN RDTACT	;  Read data active?
;;;		SKIPE WDTACT	;  Write data active?
;;;		  POP0J		;    Yes, not done yet
;;	prints/Wait feature goes here.
;;/
		SOSLE RPTCNT	;  Any repeats left?
		  JRST[	SETZM SCMLST	;No longer at last buffer
;;;			CALL SAMSET	;  Start at beginning after reseting
			call samst2	;  Just start from beg. of file for now
			POP0J ]
		SETZM SAMRUN	;  No longer running
		SETZM SAMRDY	;  No longer ready
		MOVSI RET,663000+ADSSAM		;Select for 1/4 second longer
		ADDI RET,1
		SKIPN NOMAP			;Don't map?
		  ADSMAP RET,			;  No, really do selection
		SKIPE MAILBOX+MLINT		;Interrupt requested?
		  CALL SNDINT			;  Send interrupt
		SKIPE ONCE	;  Play once more, only?
		  JRST DIE	;    Yes, then we're done!
		SKIPN GRABBY	;  Hold onto box?
		  RELEASE SAMCHN,	;  No, Let other users go
		SKIPE LOCKFL	;  Locked in core?
		  UNLOCK		;  Yes, flush that
		CALL WRASCZ↑,<[[ASCIZ/
Number of times to play: /]]>,TYOOP
		CALL TYOFLUSH
		POP0J]		;  Done!!
	CALL GETSCM,SCMSIZ	;Get a buffer size, if any commands left
	  JRST[	CALL ENDSCM	;  EOF, put out funny trailer
		POP0J]
	CALL SNDSCM,RET		;Send it to SAM
	POP0J			;Done and ready for next one

;----- MRDONE - Read data done (send another)

AUXDONE:
	SKIPN SAMRUN		;Running?
	  JRST[	CALL WRASCZ↑,<[[
ASCIZ/Bug: Read Buffer done seen with SAMRUN false!/]]>,TYOOP
		CALL DOCRLF
		POP0J ]
	SOS AUXACT		;Decrement number of active command buffers
	CALL GETAUX,AUXSIZ	;Get a buffer size, if any data left
	  POP0J			;  Nothing left, forget it
	CALL SNDAUX,RET		;Send it to SAM
	POP0J			;Done and ready for next one

;----- MWDONE - Write data done (send to disk and setup next)

OUTDONE:
	SKIPN SAMRUN		;Running?
	  JRST[	CALL WRASCZ↑,<[[
ASCIZ/Bug: Write Buffer done seen with SAMRUN false!/]]>,TYOOP
		CALL DOCRLF
		POP0J ]
	SOS OUTACT		;Decrement number of active command buffers
	CALL SNDOUT,OUTSIZ	;Write out buffer from SAM to disk
	CALL SETOUT,OUTSIZ	;Setup buffer for SAM
	POP0J			;Done and ready for next one

;----- ADCDONE - ADC buffer done (send another)

ADCDONE:
	SKIPN SAMRUN		;Running?
	  JRST[	CALL WRASCZ↑,<[[
ASCIZ/Bug: ADC Buffer done seen with SAMRUN false!/]]>,TYOOP
		CALL DOCRLF
		POP0J ]
	SOS AUXACT		;Decrement number of active command buffers
	CALL SETADC,AUXSIZ	;Setup buffer for ADC
	POP0J			;Done and ready for next one

SUBREND SIXMSG
NSUBR MSGWAIT,CODE		;Wait for specified message type
				;or other interrupt condition

	PUSHP A
ifn intbug,<	outchr ["<"]	;Fudge for matching brackets ">"
>;ifn intbug
IFN TMOENB,<
	CLKINT [2*=60*=60]	;Wait 2 minute(s) before giving up
>;IFN TMOENB
MSGWLP:	CALL WAITON,<[INTTTY!INTMAIL!INTCLK!INTTTI!INTSIX]]>
	MOVE A,RET		;Save interrupt conditions
	TLNE A,(INTTTI)
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/<esc>I interrrupt - Aborting/]]>,TYOOP
		JRST DIE]
	TLNE A,(INTTTY)		;TTY input?
	   CALL ALTCHK		;  Yes, check for <altmode>
	TRNN A,INTSIX		;SIX message?
	  JRST OTHER		;  No, some other flavor of interrupt
	CALL RCVMSG		;Get the message
	MOVEI A,INTSIX
	ANDCAB A,PENDING
	CAMN RET,CODE		;Is it the one we want?
	  JRST DONE		;  Yes, done
ifn intbug,<	outchr ["="]	>
	CALL SIXMSG		;No, process a general message
OTHER:	TLNE A,(INTMAIL)	;Mail received?
	  JRST[	CALL RDMAIL	;  Yes, read it
		JRST MSGWLP]	;  Go back for more
	TLNE A,(INTCLK)
	  JRST[	CALL WRASCZ↑,<[[ASCIZ/Timeout - Aborting/]]>,TYOOP
		JRST DIE]
	JUMPE A,MSGWLP		;All interrupts serviced
	CALL WRASCZ↑,<[[ASCIZ/Unexpectd return from WAITON, ignoring./]]>,TYOOP
	CALL DOCRLF
	JRST MSGWLP

DONE:	POPP A
ifn intbug,<			;Fudge for matching brackets "<"
	outchr [">"]
>;ifn intbug
	POP1J

SUBREND MSGWAIT
NSUBR GETSCM,COUNT		;Get SCM buffer (also GETAUX)

	MOVE RET,INADR		;Get address in file
	CAML RET,INWC		;Are there any words left in file?
	  JRST FAIL		;  No, failure (non-skip) return
	MOVE RET,COUNT		;Get number of words
	ADDB RET,INADR		;Advance pointer in file
	MOVN RET,RET		;Subtract from word count
	ADD RET,INWC		;See how far we are from end of file
	SKIPL RET		;Did we hit EOF?
	  SETZ RET,		;  No, we don't have to fudge
	ADDM RET,INADR		;Fudge in case of end of file
	ADD RET,COUNT		;Calculate number of words to read
	AOS (P)			;Take success (skip) return
FAIL:	POP1J

SUBREND GETSCM

NSUBR GETAUX,COUNT		;Get AUX buffer	

	SKIPE ADCFLG		;Using ADC?
	  JRST[	MOVE RET,COUNT	;  Yes, always use whole buffer
		JRST ALWAYS ]
	MOVE RET,AUXADR		;Get address in file
	CAML RET,AUXWC		;Are there any words left in file?
	  JRST FAIL		;  No, failure (non-skip) return
	MOVE RET,COUNT		;Get number of words
	ADDB RET,AUXADR		;Advance pointer in file
	MOVN RET,RET		;Subtract from word count
	ADD RET,AUXWC		;See how far we are from end of file
	SKIPL RET		;Did we hit EOF?
	  SETZ RET,		;  No, we don't have to fudge
	ADDM RET,AUXADR		;Fudge in case of end of file
	ADD RET,COUNT		;Calculate number of words to read
ALWAYS:	AOS (P)			;Take success (skip) return
FAIL:	POP1J

SUBREND GETAUX
NSUBR SNDSCM,COUNT		;Send command buffer to SAM (also SNDAUX)

	MOVN RET,COUNT		;Make a WCMA out of this
	MOVS RET,RET
	MOVE RET2,SCMNXT	;Get next buffer
	HRR RET,SCMWCMA(RET2)	;Set address of buffer
	MOVEM RET,DSKTO6+2	;Set in MTAPE block for disk read into P3
	MOVEM RET,TMPWCMA	;Store temporarily
	SOS DSKTO6+2		;Turn WCMA into IOWD
	MTAPE SCMCHN,DSKTO6	;Read into P3's memory!!!!!
;;;	  halt .		;**** Temporary ****
	HRRZ RET,DSKTO6+4	;errors?
	SUB RET,DSKTO6+3
	JUMPN RET,[SKIPL DSKTO6+4	;Correctable?
		  jrst[	outstr[asciz/Disk error into SIX memory. /]
			halt .]
		outstr[asciz/Correctable disk error in command channel.
/]		CALL SNDMSG,<[MECC,,SYSDEV]>,<[ECCTAB]>,RET
		CALL MSGWAIT,<[MECC,,SIXDEV]>  ;Wait for acknowledge
		JRST .+1 ]
	CALL SNDMSG,<[MCBUF,,SAMDEV]>,<[TMPWCMA]>,<[1]>
				;Tell SIX to send this to SAM
	AOS RET,SCMNXT		;Advance to next buffer
	CAML RET,NBUFS		;End of buffer right?
	  SETZM SCMNXT		;  Yes, start at beginning
	AOS SCMACT		;Increment number of active buffers
	POP1J

SUBREND SNDSCM

NSUBR SNDAUX,COUNT		;Send data buffer to SAM

	MOVN RET,COUNT		;Make a WCMA out of this
	MOVS RET,RET
	MOVE RET2,AUXNXT	;Get next buffer
	HRR RET,AUXWCMA(RET2)	;Set address of buffer
	MOVEM RET,DSKTO6+2	;Set in MTAPE block for disk read into P3
	MOVEM RET,TMPWCMA	;Store temporarily
	SKIPE ADCFLG		;For ADC?
	  JRST SKIPRD
	SOS DSKTO6+2		;Turn WCMA into IOWD
	MTAPE AUXCHN,DSKTO6	;Read into P3's memory!!!!!
;;;	  halt .		;**** Temporary ****
;;;PRINTS/Error recovery for MTAPE to read into P3 not tested yet.
;;;/
	HRRZ RET,DSKTO6+4	;errors?
	SUB RET,DSKTO6+3
	JUMPN RET,[SKIPL DSKTO6+4	;Correctable?
		  jrst[	outstr[asciz/Disk error into SIX memory. /]
			halt .]
		outstr[asciz/Correctable disk error in read data channel.
/]		CALL SNDMSG,<[MECC,,SYSDEV]>,<[ECCTAB]>,RET
		CALL MSGWAIT,<[MECC,,SIXDEV]>  ;Wait for acknowledge
		JRST .+1 ]
SKIPRD:	CALL SNDMSG,<[MRDBUF,,SAMDEV]>,<[TMPWCMA]>,<[1]>
				;Tell SIX to send this to SAM
	AOS RET,AUXNXT		;Advance to next buffer
	CAML RET,NBUFS		;End of buffer right?
	  SETZM AUXNXT		;  Yes, start at beginning
	AOS AUXACT		;Increment number of active buffers
	POP1J

SUBREND SNDAUX
NSUBR SETOUT,COUNT		;Send data buffer to SAM (also SNDOUT)

	MOVN RET,COUNT		;Make a WCMA out of this
	MOVS RET,RET
	MOVE RET2,OUTNXT	;Get next buffer
	HRR RET,OUTWCMA(RET2)	;Set address of buffer
	MOVEM RET,TMPWCMA	;Store temporarily
	CALL SNDMSG,<[MWDBUF,,SAMDEV]>,<[TMPWCMA]>,<[1]>	;Tell SIX to send this to SAM
	AOS RET,OUTNXT		;Advance to next buffer
	CAML RET,NBUFS		;End of buffer right?
	  SETZM OUTNXT		;  Yes, start at beginning
	AOS OUTACT		;Increment number of active buffers
	POP1J

SUBREND SETOUT

NSUBR SNDOUT,COUNT		;Send data buffer to disk

	MOVN RET,COUNT		;Make a WCMA out of this
	MOVS RET,RET
	MOVE RET2,OUTNXT	;Get next buffer
	HRR RET,OUTWCMA(RET2)	;Set address of buffer
	MOVEM RET,DSKFR6+2	;Set in MTAPE block for disk read into P3
	SOS DSKFR6+2		;Turn WCMA into IOWD
	MTAPE OUTCHN,DSKFR6	;Write from P3's memory!!!!!
;;;	  halt .		;**** Temporary ****
	POP1J

SUBREND SNDOUT

NSUBR SETADC,COUNT		;Send data buffer to ADC

	MOVN RET,COUNT		;Make a WCMA out of this
	MOVS RET,RET
	MOVE RET2,ADCNXT	;Get next buffer
	HRR RET,AUXWCMA(RET2)	;Set address of buffer
	MOVEM RET,TMPWCMA	;Store temporarily
	CALL SNDMSG,<[MSTBUF,,ADCDEV]>,<[TMPWCMA]>,<[1]>
				;Tell SIX to send this to ADC
	AOS RET,ADCNXT		;Advance to next buffer
	CAML RET,NBUFS		;End of buffer right?
	  SETZM ADCNXT		;  Yes, start at beginning
	AOS ADCACT		;Increment number of active buffers
	POP1J

SUBREND SETADC

NSUBR ENDSCM			;Send special trailer buffer to SAM

	MOVEI RET,SCMNOP	;Use NOP as trailer
	MOVEM RET,MSGDAT+1
	MOVE RET,[XWD MSGDAT+1,MSGDAT+2]
IFG TAILSZ-MSGMSZ-2,<	.FATAL	/Message buffer won't hold trailer!
/>
	BLT RET,MSGDAT+TAILSZ	;Make a buffer full of NOPs
	MOVE RET2,SCMNXT	;Get next buffer
	MOVSI RET,-TAILSZ
	HRR RET,SCMWCMA(RET2)	;Set address of buffer
	MOVEM RET,MSGDAT
	PUSHP RET		;Save WCMA over MSGWAIT
	CALL SNDMSG,<[MWMEM,,SIXDEV]>,<[0]>,<[1+TAILSZ]>
				;Put special trailer in next buffer
	CALL MSGWAIT,<[MWMEM,,SIXDEV]>	;Wait for acknowledge
	POPP MSGDAT		;Get back WCMA for sending to SAM
	CALL SNDMSG,<[MCBUF,,SAMDEV]>,<[MSGDAT]>,<[1]>
				;Tell SIX to send this to SAM
	SETOM SCMLST		;Mark as last buffer
	AOS RET,SCMNXT		;Advance to next buffer
	CAML RET,NBUFS		;End of buffer right?
	  SETZM SCMNXT		;  Yes, start at beginning
	AOS SCMACT		;Increment number of active buffers
	POP0J

SUBREND ENDSCM
NSUBR RCVMSG			;Recieve message from SIX

	INPUT SIXCHN,[IOWD MSGMSZ,MSGBUF]
ifn msgbug,<
	skipe debug
	call prtmsg
>;ifn msgbug
	MOVE RET,MSGBUF		;Return code for message
	AND RET,[XWD 007777,000777]	;Return only code and source
	POP0J

SUBREND RCVMSG
NSUBR SNDMSG,CODE,DATA,SIZE	;Send message to SIX (device)

	MOVE RET,CODE		;Set code for message
	TLNN RET,777		;Make sure there is a code there
	  PUSHJ P,[
	BADARG:	PUSHP RET
		CALL WRASCZ↑,<[[ASCIZ/Bad call to SNDMSG./]]>,TYOOP
		CALL DOCRLF
		POPP RET
		HALT .]
	MOVEM RET,MSGBUF
	MOVE RET,THISJOB	;Set this job's number
	DPB RET,[POINT 9,MSGBUF,26]
	AOS RET,SEQNUM		;Put in sequence number
	ANDI RET,377777
	HRL RET,SIZE		;Include number of data words
	MOVEM RET,MSGBUF+1
	HRLZ RET,DATA		;Get address of buffer
	HRRI RET,MSGDAT
	MOVE RET2,SIZE		;Get size of block
	CAILE RET2,MSGMSZ-2	;Check buffer size
	  PUSHJ P,BADARG
	TLNE RET,-1		;Are we to inhibit copy of buffer?
	SKIPN RET2		;Or is it a zero word count?
	  JRST SKPBLT		;  Yes, don't copy data!
	BLT RET,MSGDAT-1(RET2)	;Copy data into buffer
SKPBLT:	ADDI RET2,2		;Add in overhead
	MOVN RET2,RET2		;Make an IOWD
	HRLZ RET2,RET2
	HRRI RET2,MSGBUF-1
	OUTPUT SIXCHN,RET2	;Actually send message to SIX system
ifn msgbug,<
	skipe debug
	  call prtmsg
>;ifn msgbug
	POP3J			;Flush args and return

SUBREND SNDMSG
NSUBR SNDMS1,CODE		;Send one word message to SIX (device)

	MOVE RET,CODE		;Set code for message
	TLNN RET,777		;Make sure there is a code there
	  PUSHJ P,[
	BADARG:	CALL WRASCZ↑,<[[ASCIZ/Bad call to SNDMSG./]]>
		CALL DOCRLF
		HALT .]
	MOVEM RET,MSGBUF
	MOVE RET,THISJOB	;Set this job's number
	DPB RET,[POINT 9,MSGBUF,26]
	OUTPUT SIXCHN,[IOWD 1,MSGBUF]
ifn msgbug,<
	skipe debug
	call prtmsg
>;ifn msgbug
	POP1J
SUBREND SNDMS1
NSUBR PRTMSG			;Print message

	MOVE RET2,MSGBUF
	MOVEI RET,[ASCIZ/Xmt /]
	TLNE RET2,F6TO10
	  MOVEI RET,[ASCIZ/Rcv /]
	CALL WRASCZ↑,RET,TYOOP
	TLNN RET2,FNCOMP
	  JRST L1
	CALL WRASCZ↑,<[[ASCIZ/Data_error /]]>,TYOOP
L1:	TLNN RET2,FDMISS
	  JRST L2
	CALL WRASCZ↑,<[[ASCIZ/Data_missed /]]>,TYOOP
L2:
	LDB RET,[POINT 12,MSGBUF,17]
	LDB RET2,[POINT 9,MSGBUF,35]
	CALL WRMSGN↑,RET,RET2,TYOOP
	CALL WRASCZ↑,<[[ASCIZ/ Job /]]>,TYOOP
	LDB RET,[POINT 9,MSGBUF,26]
	CALL WRINT↑,RET,<[=10]>,TYOOP
	LDB RET,[POINT 9,MSGBUF,35]
	CAIL RET,NDEVS
	  SETO RET,
	CALL WRSIX↑,DVNAMS(RET),TYOOP
	TLNE RET2,FNOWDS	;One word message?
	  JRST DONE		;  Yes, done
	HLRZ RET,MSGBUF+1		;Get count
	CALL WRINT,RET,<[8]>,TYOOP	;Print word count
	CALL WRASCZ↑,<[[ASCIZ/ wds #/]]>,TYOOP
	HRRZ RET,MSGBUF+1
	CALL WROCT↑,RET,<[6]>,TYOOP
	MOVEI RET,"I"-"@"	;tab
	XCT TYOOP
	CALL WROCT↑,MSGDAT,<[=12]>,TYOOP
DONE:	CALL DOCRLF
	POP0J

	SIXBIT / ??? /
DVNAMS:	SIXBIT / SIX /
	SIXBIT / SAM /
	SIXBIT / DAC /
	SIXBIT / ADC /
	SIXBIT / FRM /
	SIXBIT / KIM /
	SIXBIT / RTJ /
NDEVS←←.-DVNAMS

SUBREND PRTMSG
NSUBR WAITON,CONDITIONS		;Wait for one of several events

ifn intbug,<	outchr ["W"]>
;Following code is complicated by the fact that you can recieve more
;than one interrupt per SIX message, and that we still want to know
;if we have gotten other interrpts.
	MOVEI RET,INTSIX	;Setup bit from SIX interrupts
	TDNN RET,CONDITIONS	;Is it a condition we are waiting for?
	  JRST DOWAIT		;  No, just wait.
	MTAPE SIXCHN,SIXMTA	;Is there a message pending?
	  JRST DOWAIT		;  No, wait for something
	ORM RET,PENDING		;Yes, process it
	INTIRQ RET,		;Get pending interrupts
	TDNE RET,CONDITIONS	;Skip if none need to be ack'ed to system
DOWAIT:	  IMSTW CONDITIONS	;Enable interrupts and wait for one
	MOVE RET,PENDING	;Get conditions
	AND RET,CONDITIONS	;Return any relevant ones
	POP1J

SUBREND WAITON
;----- INTSER			;Interrupt service routine

INTSER:	INTMSK [0]		;Clear interrupt mask
	MOVE RET,JOBCNI		;OR conditions into those which haven't
	ORM RET,PENDING		;been processed at user level
	DISMIS			;And done (this shouldn't even have to
				;be done at interrupt level!!!!!)
NSUBR SNDINT			;Send interrupt to calling program

	MOVE RET,MAILBOX+MLJOB	;Setup block for UUO
	MOVE RET+1,MAILBOX+MLINT
	INTIPI RET		;Send the interrupt
	  JFCL			;  Ignore it if it fails
	POP0J

SUBREND SNDINT
NSUBR SWNUM			;Get number from switch name (from FCOPY)

SWNUM:	CALL(RDSIX↑,<[PUSHJ P,CMDGET]>,[SWBRK])
COMMENT ⊗
	MOVSI 2,-SWCNT
	CAME 1,SWTAB(2)
	AOBJN 2,.-1
	JUMPGE 2,[FATAL(Unknown switch)]
	HRRZ 2,2
	POP0J
⊗;
	SETZM SWMATCH#		;Number of matches less one
	SKIPN 3,1		;Make sure switch was given and save switch
	JRST SWUNKN
	MOVSI 2,(<POINT 6,0,35>);Turn spaces (00) into (77)
SWNUM2:	ILDB 4,2
	JUMPN 4,NOTSPA
	MOVEI 4,77
	DPB 4,2
NOTSPA:	CAME 2,[POINT 6,1,35]	;All of word done?
	JRST SWNUM2		;No
	SETCM 4,1		;Compliment it
	MOVSI 2,-SWCNT
;2 now contains AOBJN pointer for switchs
;3 now contains bits which must be on to recognize switch name
;4 now contains bits which must be off to recognize switch name
SWNUM3:	TDNE 4,SWTAB(2)		;All bits off that need be?
	AOBJN 2,SWNUM3		;No, try again (if more, else continue and fail later)
	SETCM 1,SWTAB(2)	;Pick up compliment of switch
	TDNN 2,1		;All needed bits on?
SWNUM4:	AOBJN 2,SWNUM3		;No, try again (if more, else continue and fail later)
	SKIPE SWMATCH		;Previous match?
	JRST [	JUMPL 2,[CALL WRASCZ↑,<[[ASCIZ/Ambiguous switch/]]>,TYOOP
			 JRST DIE]		;And if not end, lose
		HRRZ 2,SWMATCH		;Return match
		POPJ P,]
	MOVEM 2,SWMATCH		;Save last match
	JUMPL 2,SWNUM4		;And go back for more, unless already at end of list
SWUNKN:	CALL WRASCZ↑,<[[ASCIZ/Unknown switch. /]]>
	JRST DIE

;Break table for reading switches
SWBRK:	BYTE (32) -1 (1) 0 (3) -1			;<null> thru  #
	BYTE (2) 0 (10) -1 (10) 0 (6) -1 (1) -1 (7) 0	;$ thru G
	BYTE (19) 0 (5) -1 (1) -1 (11) 0		;H thru k
	BYTE (15) 0 (5) -1 (16) 0			;l thru <bs>

SUBREND SWNUM
;Typeout to arbitrary TTY, using NULMES

TYOOP:	PUSHJ P,PUTCHR

PUTCHR:	SOSLE TYOLFT		;Space left in buffer
	  JRST[	IDPB 1,TYOPTR	;Stuff character in output buffer
		POPJ P,]	;And return
	PUSHJ P,TYOFLU		;  No, output it to get some more
	  JRST PUTCHR
	HALT PUTCHR

TYOFLU:	PUSH P,1		;Save register
	MOVE 1,[POINT 7,TYOBUF]	;Reset pointer to beginning of buffer
	MOVEM 1,TYOPTR		;Setup pointer for NULMES
	MOVEI 1,TYOSIZ		;Calculate count
	SUB 1,TYOLFT
	JUMPE 1,PUTOU9		;If nothing to do, skip it!
	DPB 1,[POINT 12,TYOPTR,17]
	PUSH P,1		;Save count on stack
PUTOU2:	MOVEI 1,TYOTTY		;Setup UUO block for NULMES
	NULMES 1,
	  JRST[	JUMPE 1,PUTOU9	;*** No one home if none left to print????
		PUSH P,1	;Save count left on stack
		MOVE 1,-1(P)	;Get original count
		SUB 1,(P)	;this gives number of characters sent
		  JUMPE 1,[MOVEI 1,=3	;Holding, wait a while this time
			   SLEEP 1,
			   JRST PUTOU2]
		PUSH P,2	;IDIV will clobber AC 2
		IDIVI 1,5	;Convert byte count into word count and
				;remainder
		ADDM 1,TYOPTR	;Increment word part of pointer
		SKIPE 2		;Skip over first decrement if exact word count
	PUTOU3:	IBP TYOPTR	;Increment pointer for each in remainder
		SOJG 2,PUTOU3
		POP P,-1(P)	;Put new count where old count was
		MOVEI 1,1	;Sleep a second
		SLEEP 1,
		JRST PUTOU2]
PUTOU9:	POP P,1			;Flush stack
	MOVEI 1,TYOSIZ		;Set number of characters left
	MOVEM 1,TYOLFT
	MOVE 1,[POINT 7,TYOBUF]	;Reset pointer to beginning of buffer
	MOVEM 1,TYOPTR		;Setup pointer for NULMES
	POP P,1
	POPJ P,

;Output a CRLF and flush out buffer
DOCRLF:	MOVEI 1,15		;CR
	PUSHJ P,PUTCHR
	MOVEI 1,12		;LF
	PUSHJ P,PUTCHR
	PUSHJ P,TYOFLUSH	;Force out line
	POPJ P,

;Get character from command string.  This could also be made to read
;from a command file
CMDGET:	INCHWL 1		;Get a character, activate on end of line
	SOS RESCNT		;For initialization
	POPJ P,

;Data area

BEGZER::	;Beginning of area zeroed on (re)initialization

SCMWCMA: BLOCK MAXBFS	;Buffer addresses in SIX (in WCMA form)
AUXWCMA: BLOCK MAXBFS	;Buffer addresses in SIX (in WCMA form)
OUTWCMA: BLOCK MAXBFS	;Buffer addresses in SIX (in WCMA form)
TMPWCMA: BLOCK 1	;Use to store partial WCMA prior to SNDMSG
SCMNXT:	 BLOCK 1	;Next buffer for commands
SCMACT:	 BLOCK 1	;Number of buffers active
SCMLST:	 BLOCK 1	;Flag indicating trailing buffer has been sent
AUXNXT:	 BLOCK 1	;Next buffer for read data
AUXACT:	 BLOCK 1	;Number of buffers active
OUTNXT:	 BLOCK 1	;Next buffer for write data
OUTACT:	 BLOCK 1	;Number of buffers active
ADCFLG:	 BLOCK 1	;If non-zero, then reading data from ADC, not DSK
ADCNXT:	 BLOCK 1	;Next buffer for ADC data
ADCACT:	 BLOCK 1	;Number of buffers active
RDAFLG:	 BLOCK 1	;Read data in use
SAMRDY:	 BLOCK 1	;Flag indicating SAM ready to run
SAMRUN:	 BLOCK 1	;Flag indicating SAM is already running

WAITIME: BLOCK 1	;If non-negative, number of seconds to wait
			;between plays
RPTCNT:	 BLOCK 1	;Number of times left to play
ONCE:	 BLOCK 1	;If nonzero, play once and then leave
WAITFL:	 BLOCK 1	;Always wait
NOMAP:	 BLOCK 1	;Disable mapping of console speaker
GRABBY:	 BLOCK 1	;Hold onto Box between plays
TAPEFL:	 BLOCK 1	;Taping (don't start until GO)
MEMDEB:	 BLOCK 1	;Print memory buffer addresses (if non-zero)
LOCKFL:	 BLOCK 1	;Lock job in core during play (or tape)
PACKED:	 BLOCK 1	;Packed (16 bit) (if non-zero)
OVERWR:	 BLOCK 1	;Overwrite output file

THISJOB: BLOCK 1	;This job's numer

;Message buffer for SIX
		;↓↓↓ NEXT TWO LINES MUST BE KEPT IN ORDER
MSGBUF:	 BLOCK 2	;Header for SIX message
MSGDAT:	 BLOCK MSGMSZ	;Data for SIX message
		;↑↑↑ PREVIOUS TWO LINES MUST BE KEPT IN ORDER

;Pending interrupts
PENDING: BLOCK 1

;Buffer for messages from controlling program (if run detached)
MAILBOX: BLOCK =32

;Special block for SIX MTAPE (to see if anything is waiting)
SIXMTA:	 BLOCK 2

;Type out buffer
TYOLFT:	0		;Number of characters left in buffer
TYOTTY:	-1		;TTY number to use
TYOPTR:	0		;Pointer to buffer
TYOBUF:	BLOCK	=80/5	;Type out buffer
TYOSIZ←← 5*(.-TYOBUF)	;Length of type out buffer

ENDZER←←.-1

;Parameters controlling buffer allocation
NBUFS:	3		;Number of buffers to use (default 3)
SCMSIZ:	=9*=128		;Size of SCM buffer on SIX
AUXSIZ:	=2*=18*=128	;Size of AUX buffer on SIX
OUTSIZ:	=18*=128	;Size of OUT buffer on SIX
SEQNUM:	 0		;Sequence number for next message

;Input specification block for RDFILN, OPEN and LOOKUP
INBLK:	17		;Device mode
INDEV:	SIXBIT/DSK/	;Device name
	XWD 0,INHDR	;Pointers to buffer headers
INFILE:	SIXBIT/TEST/	;SIXBIT/Filename/
	SIXBIT/SAM/	;SIXBIT/Extension/ (Other info. returned in right half)
	BLOCK 1		;(Date and protection returned here)
	BLOCK 1		;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
;;INFILE:	BLOCK 1		;SIXBIT/Filename/
;;	BLOCK 1		;SIXBIT/Extension/ (Other info. returned in right half)
;;	BLOCK 1		;(Date and protection returned here)
;;	BLOCK 1		;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
			;Negative swapped length returned here by LOOKUP

;Input buffer header for OPEN, IN
INHDR:	BLOCK 3

;Addressing
INWC:	BLOCK 1		;Number of words in file
INADR:	BLOCK 1		;Current address in file

;Read data specification block for RDFILN, OPEN and LOOKUP
AUXBLK:	17		;Device mode
AUXDEV:	SIXBIT/DSK/	;Device name
	XWD 0,AUXHDR	;Pointers to buffer headers
AUXFIL:	BLOCK 1		;SIXBIT/Filename/
	BLOCK 1		;SIXBIT/Extension/ (Other info. returned in right half)
	BLOCK 1		;(Date and protection returned here)
	BLOCK 1		;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
			;Negative swapped length returned here by LOOKUP

;Input buffer header for OPEN, IN
AUXHDR:	BLOCK 3

;Addressing
AUXWC:	BLOCK 1		;Number of words in file
AUXADR:	BLOCK 1		;Current address in file

;Output specification block for RDFILN, OPEN and LOOKUP
OUTBLK:	17		;Device mode
OUTDEV:	SIXBIT/DSK/	;Device name
	XWD 0,OUTHDR	;Pointers to buffer headers
OUTFIL:	BLOCK 1		;SIXBIT/Filename/
	BLOCK 1		;SIXBIT/Extension/ (Other info. returned in right half)
	BLOCK 1		;(Date and protection returned here)
	BLOCK 1		;XWD 'Proj','Prog' (XWD proj,prog for DEC systems)
			;Negative swapped length returned here by LOOKUP

;Input buffer header for OPEN, IN
OUTHDR:	BLOCK 3

;Special MTAPE block for writing from SIX memory
DSKFR6:	SIXBIT /GODMOD/
	25		;Write disk in dump mode into P3 memory
	0		;IOWD in P3 memory
	0		;Special addressing for old-mode UDP

;Special MTAPE block for reading into SIX memory
DSKTO6:	SIXBIT /GODMOD/
	24		;Read disk in dump mode into P3 memory
	0		;IOWD in P3 memory
	ECCTAB		;Table for ECC (error correct code) data
	0		;ECC status word 1
	0		;ECC status word 2
	0		;Special addressing for old-mode UDP
ECCTAB:	BLOCK =38	;Table to hold error correction information

;Rescan count
RESCNT:	BLOCK 1

;Debug
DEBUG:	0

;Patch areas are good for you
PATCH↑:	BLOCK 40

;Pushdown List (or Stack)
PDL:	BLOCK 40
PDLIOW:	IOWD .-PDL,PDL		;By putting this immediately after PDL, one
				;can find the beginning just from P.  Used
				;to print backtrace (a la LISP)
END